<template>
    <!-- 弹框组件 -->
    <Teleport to="body">
        <Transition name="modal-fade">
            <div v-if="modelValue" class="modal-overlay" @click="handleOverlayClick">
                <div class="modal-container" :style="modalSyle" @mousedown="startDrag" @mousemove="onDrag"
                    @mouseup="stopDrag" @mouseleave="stopDrag">
                    <!-- 头部标题栏 -->
                    <div class="modal-header">
                        <!-- 左边的标题栏 -->
                        <slot name="header-title">
                            {{ title }}
                        </slot>
                        <!-- 右边的按钮栏 -->
                        <button class="modal-close" @click="close">X</button>
                    </div>
                    <!-- body内容区 -->
                    <div class="modal-body">
                        <slot>
                            {{ content }}
                        </slot>
                    </div>
                    <!-- 底部按钮区 -->
                    <div class="modal-footer">
                        <slot name="footer">
                            <button class="modal-btn cancel" v-if="showCancel" @click="cancel">{{ cancelBtnTitle
                                }}</button>
                            <button class="modal-btn confirm" @click="confirm">{{ confirmBtnTitle }}</button>
                        </slot>
                    </div>
                </div>
            </div>
        </Transition>
    </Teleport>
</template>
<script lang="ts" setup>
import { computed, onMounted, onUnmounted, ref } from 'vue';
const props = defineProps({
    modelValue: Boolean, //v-modelValue绑定值
    title: { //标题
        type: String,
        default: '提示'
    },
    content: String, //中间的内容
    cancelBtnTitle: { //取消的按钮文字
        type: String,
        default: '取消'
    },
    confirmBtnTitle: { //确认的按钮文字
        type: String,
        default: '确认'
    },
    showCancel: { //是否显示取消按钮
        type: Boolean,
        default: true
    },
    width: { //弹框宽度
        type: [String, Number],
        default: '500px'
    },
    height: { //弹框高度
        type: [String, Number],
        default: 'auto'
    },
    closeOnClickOverlay: {
        type: Boolean,
        default: true
    },
    draggable: { //是否拖拽
        type: Boolean,
        default: true
    },
})

const emit = defineEmits(['update:modelValue', 'confirm', 'cancel'])
//处理拖拽逻辑
const isDragging = ref(false);
const dragOffset = ref({ x: 0, y: 0 });
const position = ref({ x: 0, y: 0 });

const modalSyle = computed(() => {
    return {
        width: typeof props.width === 'number' ? `${props.width}px` : props.width,
        height: typeof props.height === 'number' ? `${props.height}px` : props.height,
        transform: `translate(${position.value.x}px, ${position.value.y}px)`
    }
})
//开始拖拽
const startDrag = (event: any) => {
    if (!props.draggable) return;

    //只有点击标题栏时才可以拖动
    if (event.target.closest('.modal-header')) {
        isDragging.value = true;
        dragOffset.value = {
            x: event.clientX - position.value.x,
            y: event.clientY - position.value.y
        };
    }
}
const onDrag = (event: any) => {
    if (isDragging.value) {
        position.value = {
            x: event.clientX - dragOffset.value.x,
            y: event.clientY - dragOffset.value.y
        }
    };
}
//结束拖拽
const stopDrag = () => {
    isDragging.value = false;
}
//取消
const cancel = () => {
    emit('cancel');
    close();
}
//确认
const confirm = () => {
    emit('confirm');
    close();
}
//关闭
const close = () => {
    emit('update:modelValue', false);
}
const handleOverlayClick = (event: any) => {
    if (props.closeOnClickOverlay && event.target.classList.contains('modal-overlay')) {
        close();
    }
}

//判断按ESC键关闭弹框
const handleKeyDown = (event: any) => {
    if (event.key === 'Escape' && props.modelValue) {
        close();
    }
}
//监听按键
onMounted(() => {
    window.addEventListener('keydown', handleKeyDown);
})
//移除按键
onUnmounted(() => {
    window.removeEventListener('keydown', handleKeyDown);
})
</script>
<style lang="scss" scoped>
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 1000;
}

.modal-container {
    background-color: #fff;
    border-radius: 4px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.15);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    max-width: 90%;
    max-height: 90%;
}

.modal-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    border-bottom: 1px solid #e8e8e8;

    .modal-close {
        border: none;
        background: transparent;
        font-size: 20px;
        cursor: pointer;
        outline: none;
    }
}

.modal-body {
    padding: 16px;
    overflow-y: auto;
    flex: 1;
}

.modal-footer {
    padding: 12px 16px;
    border-top: 1px solid #e8e8e8;
    text-align: right;

    .modal-btn {
        padding: 8px 15px;
        margin-left: 10px;
        border-radius: 4px;
        border: 1px solid #dcdfe6;
        background: #fff;
        cursor: pointer;
    }

    .confirm {
        background: #409eff;
        color: #fff;
        border-color: #409eff;
    }
}

.modal-fade-enter-active,
.modal-fade-leave-active {
    transition: opacity 0.3s;
}

.modal-fade-enter-from,
.modal-fade-leave-to {
    opacity: 0;
}
</style>